package ascii;

import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.functions.Function;
import okio.ByteString;
import org.junit.Test;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.List;

public class Test3 {
    @Test
    public void addition_isCorrect() throws Exception {
        String hex = "ad18112600000900000000068910f02e708140ab9a0604f4782424d92070cb340002cac804056320000603603009038578080e32e0100d1d016034dc088193c02e044e80800d150100629407008220280b8480a0090625c03024b481109b3b0502bd181d0caf3094259cc2401e12088000001d01c320840d25c2d009028f90c6014882b8053f0a6025442a81d2d0b6032c8338042e0e00184c3101e580a802b702900901b5d0a013e2c2507f6f09829c242507a8107c0b89c1c0000c062061001681c9c068043e01b009035220600f49c1702cdf07407184210080d0740c88c1c03a6607011ad81e03afc07413c401a0080a73c3009ac858050a0a00034120391428193c8485499078d1480e1da980e42540080823a88064245c58465a9543c351794482092fa9822618806cc748058cd44000000000";
        final ByteBuffer buffer = ByteString.decodeHex(hex).asByteBuffer();

        buffer.order(ByteOrder.LITTLE_ENDIAN);
        int startX = buffer.getShort() & 0xFFFF;
        int startY = buffer.getShort() & 0xFFFF;
        int startP = buffer.getShort() & 0xFFFF;

        Observable<NotePenPointerVector> vectors = Observable.empty();
        while (buffer.hasRemaining()) {
            int numberSizeByBit = buffer.get() & 0xFF;
            int totalSizeByBit = (numberSizeByBit + 1) * 3 * 10;
            int totalSizeByByte = totalSizeByBit / Byte.SIZE + (totalSizeByBit % Byte.SIZE == 0 ? 0 : 1);

            final byte[] bytes = new byte[totalSizeByByte];
            buffer.get(bytes);

            vectors.concatWith(parseVectors(bytes, numberSizeByBit));

            System.out.println("xiaoma");
        }
    }

    private Observable<NotePenPointerVector> parseVectors(final byte[] bytes, int numberSizeByBit) {
        Observable<Integer> bitObservable = Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> e) throws Exception {
                for (int i = 0; i < bytes.length; i++) {
                    for (int bitIndex = 0; bitIndex < Byte.SIZE; bitIndex++) {
                        e.onNext((bytes[i] & (1 << bitIndex)) != 0 ? 1 : 0);
                    }
                }
            }
        });

        Observable<Integer> numberObservable = bitObservable.buffer(numberSizeByBit).map(new Function<List<Integer>, Integer>() {
            @Override
            public Integer apply(List<Integer> bits) throws Exception {
                boolean positive = bits.get(0) != 0;

                int res = 0;
                for (int i = 1; i < bits.size(); i++) {
                    res = res << 1 + bits.get(0);
                }

                return res * (positive ? 1 : -1);
            }
        });

        return numberObservable.buffer(3).map(new Function<List<Integer>, NotePenPointerVector>() {
            @Override
            public NotePenPointerVector apply(List<Integer> integers) throws Exception {
                return new NotePenPointerVector(integers.get(0), integers.get(1), integers.get(2));
            }
        });
    }

    public static class NotePenPointerVector {
        public int vectorX;
        public int vectorY;
        public int vectorP;

        public NotePenPointerVector(Integer vectorX, Integer vectorY, Integer vectorP) {
            this.vectorX = vectorX;
            this.vectorY = vectorY;
            this.vectorP = vectorP;
        }
    }
}
